package com.ruoyi.inspection.controller;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.GlobalConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.inspection.config.GovernTaskConfig;
import com.ruoyi.inspection.domain.receiveVo.*;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.*;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * http://localhost:38080/govern/warn/crow
 */
@Slf4j
@RestController
@RequestMapping("/govern/warn/")
public class GovernWarnInfoPush {
    @Resource
    private PushInfoMapper pushInfoMapper;
    @Autowired
    private IPersonCrowdAlertService personCrowdAlertService;

    @Autowired
    private KeyPersonnelAdminService keyPersonnelAdminService;
    @Autowired
    private TemporaryStaffAccountService temporaryStaffAccountService;


    /*******************人员聚集 * 每间隔5分钟推送一次 *人员聚集 ****************/
    @Scheduled(cron = "0 0/5 * * * ?")
    public void PersonCrowdScheduleTask() {
        pushPersonCrowd();
    }


    // 人员聚集上报
    @GetMapping("/crow")
    public AjaxResult pushJobAttachment() {
        pushPersonCrowd();

        return AjaxResult.success();
    }

    /**
     * 推送人员聚集数据 到市局
     */
    public boolean pushPersonCrowd() {
        // 查询最近5分钟的人员聚集数据
        List<PersonCrowdAlert> crowdList = Optional.ofNullable(
                personCrowdAlertService.selectAboutFiveMinutesAgo()
        ).orElse(Collections.emptyList());

        List<ReceivePersonCrowd> convertedList = new ArrayList<>();

        // 无原始数据时直接处理空推送
        if (crowdList.isEmpty()) {
            log.info("推送市局端：近5分钟无人员聚集报警数据，执行空推送");
            return pushHandler(convertedList);
        }

        // 转换原始数据（增加转换数量日志）
        log.info("推送市局端：开始转换 {} 条人员聚集原始数据", crowdList.size());
        for (PersonCrowdAlert crowdAlert : crowdList) {
            ReceivePersonCrowd converted = convertToReceivePersonCrowd(crowdAlert);
            if (converted != null) {
                convertedList.add(converted);
            }
        }
        log.info("推送市局端：原始数据转换完成，有效数据 {} 条", convertedList.size());


        // 推送并更新状态（重命名变量提升可读性）
        boolean isEmptyConvertedList = convertedList.isEmpty();
        boolean pushSuccess = pushHandler(convertedList);
        if (!pushSuccess) {
            log.error("推送市局端失败：推送 {} 条数据", convertedList.size());
            return false;
        }
        boolean updateSuccess = isEmptyConvertedList
                ? updateHandler(crowdList, 2)
                : updateHandler(crowdList, 1);

        return updateSuccess; // 返回整体处理结果
    }

    /**
     * 推送人员聚集数据 到市局
     * @param list
     * @return
     */
    public boolean pushHandler(List<ReceivePersonCrowd> list) {
        // 无数据时添加空推送对象
        if (list.isEmpty()) {
            list.add(createEmptyCrowdData());
        }

        // 推送核心逻辑（增加异常捕获和结果校验）
        String url = GovernTaskConfig.receivePersonCrowdList;
        try {
            String jsonData = JSONUtil.toJsonPrettyStr(list);
            String pushResult = GovernTaskConfig.pushData(jsonData, url);

            pushInfoMapper.insert(pushResult);
            log.info("推送市局端成功：推送 {} 条数据，结果已记录", list.size());
            return true;
        } catch (Exception e) {
            log.error("推送市局端异常：URL={}, 数据={}", url, JSONUtil.toJsonStr(list), e);
            return false;
        }
    }

    // 新增：创建空推送数据对象（代码复用）
    private ReceivePersonCrowd createEmptyCrowdData() {
        ReceivePersonCrowd emptyCrowd = new ReceivePersonCrowd();
        emptyCrowd.setCompanyCode(GlobalConstants.COMPANY_CODE);
        emptyCrowd.setTimeStamp(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
        emptyCrowd.setAlarmArea(Collections.emptyList());
        return emptyCrowd;
    }

    /**
     * 更新人员聚集数据上报状态
     * @param crowdList
     * @param status
     * @return
     */
    public boolean updateHandler(List<PersonCrowdAlert> crowdList, int status) {
        // 空列表直接返回成功（避免无效操作）
        if (crowdList == null || crowdList.isEmpty()) {
            log.info("更新上报状态：无数据需更新，状态值：{}", status);
            return true;
        }

        try {
            // 批量构建更新对象（若IPersonCrowdAlertService支持批量更新，可替换为batchUpdate）
            List<PersonCrowdAlert> updateEntities = crowdList.stream()
                    .map(alert -> {
                        PersonCrowdAlert entity = new PersonCrowdAlert();
                        entity.setId(alert.getId());
                        entity.setIsUpload(status);
                        entity.setUpdateBy("admin");
                        entity.setUpdateTime(new Date());
                        return entity;
                    })
                    .collect(Collectors.toList());

            // 批量更新
            personCrowdAlertService.batchUpdate(updateEntities);
            log.info("更新上报状态成功：共更新 {} 条数据，状态值：{}", crowdList.size(), status);
            return true;
        } catch (Exception e) {
            log.error("更新上报状态异常：状态值={}", status, e);
            return false;
        }
    }

    /**
     * 人员聚集数据转换
     * @param crowdAlert
     * @return
     */
    public ReceivePersonCrowd convertToReceivePersonCrowd(PersonCrowdAlert crowdAlert) {
        if (StringUtils.isEmpty(crowdAlert.getPoint())) {
            return null;
        }

        Date raiseTime = crowdAlert.getRaiseTime();
        if (raiseTime == null) {
            log.error("人员聚集数据转换失败：raiseTime字段为空，告警ID：{}", crowdAlert.getId());
            return null;
        }

        JSONObject jsonObject = JSONObject.parseObject(crowdAlert.getPoint());
        List<ReceivePersonCrowd> personList = pojoPersonInfo(jsonObject, crowdAlert.getTags());
        if (StringUtils.isEmpty(personList)) {
            return null;
        }

        ReceivePersonCrowd crowd = new ReceivePersonCrowd();
        crowd.setCompanyCode(GlobalConstants.COMPANY_CODE);
        crowd.setTimeStamp(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", raiseTime));
        List<List<ReceivePersonCrowd>> alarmArea = Collections.singletonList(personList);
        crowd.setAlarmArea(alarmArea);
        return crowd;
    }

    /**
     * 人员聚集数据转换
     * @param jsonObject
     * @param tagIds
     * @return
     */
    public List<ReceivePersonCrowd> pojoPersonInfo(JSONObject jsonObject, String tagIds) {
        if (StringUtils.isEmpty(tagIds)) { return null; }
        String[] tagIdAry = tagIds.split(",");
        if (tagIdAry.length==0) { return null; }

        JSONObject entitys = jsonObject.getJSONObject("entitys");
        if (entitys==null) { return null; }

        List<ReceivePersonCrowd> list = new ArrayList<>();
        TemporaryStaffAccount tempAccount = null;
        ReceivePersonCrowd personVo = null;
        KeyPersonnelAdmin person = null;

        for (String tagId : tagIdAry) {
            JSONObject tagObj = entitys.getJSONObject(tagId);
            if (tagObj==null) {
                continue;
            }

            String personType = tagObj.getString("entityType");
            String userName = tagObj.getString("name");
            personVo = new ReceivePersonCrowd();
            personVo.setName(userName);
            personVo.setX(String.format("%.6f", tagObj.getFloatValue("lon")) );
            personVo.setY(String.format("%.6f", tagObj.getFloatValue("lat")));

            if ("contractor".equals(personType)) {
                tempAccount = temporaryStaffAccountService.selectByName(userName);
                if (tempAccount==null)  { continue; }
                personVo.setPersonId(tempAccount.getGovernId());
                personVo.setPersonType("02");
            } else if ("staff".equals(personType)) {
                person = keyPersonnelAdminService.selectByName(userName);
                if (person==null)  { continue; }
                personVo.setPersonId(person.getGovernId());
                personVo.setPersonType("01");
            } else {
                continue;
            }

            list.add(personVo);
        }

        return list;
    }

}
